from rest_framework import serializers
from .models import User
import re
from django_redis import get_redis_connection

from rest_framework_jwt.settings import api_settings

class RegisterCreateSerializer(serializers.ModelSerializer):

    password2=serializers.CharField(label='校验密码',allow_null=False,write_only=True)
    sms_code=serializers.CharField(label='短信验证码',max_length=6,min_length=6,allow_null=False,allow_blank=False,write_only=True)
    allow=serializers.CharField(label='是否同意协议',allow_null=False,allow_blank=False,write_only=True)

    token=serializers.CharField(label='登录状态token',read_only=True)


    class Meta:
        model=User
        fields=('id','username','password','mobile','password2','sms_code','allow','token')
        extra_kwargs={
            'id':{'read_only':True},
            'username':{
                'min_length':5,
                'max_length':20,
                'error_messages':{
                    'min_length':'仅允许5-20个字符的用户名',
                    'max_length':'仅允许5-20个字符的用户名',
                }
            },
            'password':{
                'write_only':True,
                'min_length':8,
                'max_length':20,
                'error_messages':{
                    'min_length':'仅允许8-20个字符的密码',
                    'max_length':'仅允许8-20个字符的密码',
                }
            }
        }
    #     进行校验
    # validate_字段名 是进行单字段验证 手机号和是否同意协议
    def validate_mobile(self, value):
        if not re.match(r'1[345789]\d{9}',value):
            raise serializers.ValidationError('手机号格式不正确')
        return value

    def validate_allow(self,value):
        if value!='true':
            raise serializers.ValidationError('您未同意协议')
        return value

    # 实现多字段验证 密码和短信是否一致
    # 数据都在attrs里
    def validate(self, attrs):
        # 拿到数据
        password=attrs['password']
        password2=attrs['password2']
        # 比较数据
        if password!=password2:
            raise serializers.ValidationError('密码不一致')
        # 比较手机验证码
        # 获取用户提交的验证码
        code=attrs['sms_code']
        # 获取Redis里的验证码
        redis_conn=get_redis_connection('code')

        # 获取手机号码
        mobile=attrs['mobile']
        redis_code=redis_conn.get('sms_%s'%mobile)

        if redis_code is None:
            raise serializers.ValidationError('验证码过期')

        if redis_code.decode()!=code:
            raise serializers.ValidationError('验证码不正确')
        return attrs

    def create(self, validated_data):
        # 因为这三个字段只是用来验证，所以不需要入库，
        # 再入库前删除
        del validated_data['password2']
        del validated_data['sms_code']
        del validated_data['allow']


        user=super().create(validated_data)

        user.set_password(validated_data['password'])
        user.save()
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        user.token = token

        return user


class UserCenterInfoSerializer(serializers.ModelSerializer):
    class Meta:
        model=User
        fields=['username','mobile','email','id','email_active']

class UserEmailSerializer(serializers.ModelSerializer):
    class Meta:
        model=User
        fields=['email']
        extra_kwargs={
            'email':{
                'required':True
            }
        }

    def update(self,instance,validated_data):
        email=validated_data.get('email')
        instance.email=email
        instance.save()
        # TODO 由于async成了关键字，有些模块不能在Python 3.7里使用，先忽略
        # from celery_tasks.email.tasks import send_active_email
        # send_active_email.delay(email,instance,id)
        return instance

# ############################################################################################################
# from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
# from mall.mall import settings
#
# # 1. 创建序列化器
# s = Serializer(secret_key=settings.SECRET_KEY,expires_in=300)
#
# #2.组织数据
# data = {
#     'id':10,
#     'email':'qi_rui_hua@163.com'
# }
#
# #3.对数据进行加密
# token = s.dumps(data)
#
#
#
# s.loads(token)